﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Web.Script.Serialization;
using System.Xml.Linq;
//
using PerceptiveMCAPI.Types.Internal;
//
namespace PerceptiveMCAPI.Types
{
	public class campaignAnalyticsOutput : Api_BaseOutput
	{
		public campaignAnalyticsResults result { get; set; }
		public campaignAnalyticsParms inputParms { get; private set; }
		// --------------------------------------------------------
		public campaignAnalyticsOutput( campaignAnalyticsInput input )
			: base( input )
		{
			inputParms = input.parms;
		}
		// --------------------------------------------------- tostring
		public override string ToString()
		{
			if ( this.result != null )
				return string.Format( "Visits: {0}, Pages:{1}, Trans:{2}, Revenue:{3}",
					this.result.visits, this.result.pages, this.result.transactions, this.result.revenue );
			else
				return "Results are not available";
		}

		#region ================================================================== format setup

		// ---- serial
		internal void Format( string api_Request, string api_Response )
		{
			this.api_Request = api_Request;
			this.api_Response = api_Response;
			// ----------------------------------
			if ( this.api_OutputType == EnumValues.OutputType.JSON )
				outputJSON();
			else if ( this.api_OutputType == EnumValues.OutputType.XML )
				outputXML();
		}

		// ---- xmlrpc
		internal void Format( x_campaignAnalytics rpcResult )
		{
			this.api_Request = EnumValues.NotSupplied;
			this.api_Response = EnumValues.NotSupplied;
			// ------------------------
			this.result = FormatResults( rpcResult );
		}

		#endregion

		#region ================================================================= Output

		// ---------------------------------------------------------- outputXML
		private void outputXML()
		{
			XElement xml = XElement.Parse( this.api_Response );
			// error check
			Api_Error error = apiSerial.GetXmlOutputError( xml );
			if ( error != null )
			{
				this.api_ErrorMessages.Add( error );
				return;
			}
			// -------------------------------------------- get values
			try
			{
				int it; double dbl;
				campaignAnalyticsResults result = new campaignAnalyticsResults();

				int.TryParse( xml.Element( "visits" ).Value, out it );
				result.visits = it;
				int.TryParse( xml.Element( "pages" ).Value, out it );
				result.pages = it;
				int.TryParse( xml.Element( "new_visits" ).Value, out it );
				result.new_visits = it;
				int.TryParse( xml.Element( "bounces" ).Value, out it );
				result.bounces = it;
				double.TryParse( xml.Element( "time_on_site" ).Value, out dbl );
				result.time_on_site = dbl;
				int.TryParse( xml.Element( "goal_conversions" ).Value, out it );
				result.goal_conversions = it;
				double.TryParse( xml.Element( "goal_value" ).Value, out dbl );
				result.goal_value = dbl;
				double.TryParse( xml.Element( "revenue" ).Value, out dbl );
				result.revenue = dbl;
				int.TryParse( xml.Element( "transactions" ).Value, out it );
				result.transactions = it;
				int.TryParse( xml.Element( "ecomm_conversions" ).Value, out it );
				result.ecomm_conversions = it;
				// goals -------------------------
				if ( xml.Element( "goals" ).HasElements )
				{
					IEnumerable<XElement> goals = xml.Element( "goals" ).Descendants( "struct" );
					foreach ( XElement goal in goals )
					{
						string name = goal.Element( "name" ).Value;
						int.TryParse( goal.Element( "conversions" ).Value, out it );
						result.goals.Add( name, it );
					}
				}
				this.result = result;
			}
			catch ( Exception ex )
			{
				this.api_ErrorMessages.Add( apiException.FormatError( ex ) );
			}
		}

		// ---------------------------------------------------------- outputJSON
		private void outputJSON()
		{
			JavaScriptSerializer jss = new JavaScriptSerializer();

			try
			{
				if ( this.api_Response.Contains( EnumValues.JSONErrorString ) )
				{
					Api_Error err = jss.Deserialize<Api_Error>( this.api_Response );
					this.api_ErrorMessages.Add( err );
				}
				else
				{
					x_campaignAnalytics jsonResult = jss.Deserialize<x_campaignAnalytics>( this.api_Response );
					this.result = FormatResults( jsonResult );
				}
			}
			catch ( Exception ex )
			{
				this.api_ErrorMessages.Add( apiException.FormatError( ex ) );
			}
		}

		// ---------------------------------------------------------- FormatResults
		private campaignAnalyticsResults FormatResults( x_campaignAnalytics x_results )
		{
			campaignAnalyticsResults result = new campaignAnalyticsResults();
			result.visits = x_results.visits;
			result.pages = x_results.pages;
			result.new_visits = x_results.new_visits;
			result.bounces = x_results.bounces;
			result.time_on_site = x_results.time_on_site;
			result.goal_conversions = x_results.goal_conversions;
			result.goal_value = x_results.goal_value;
			result.revenue = x_results.revenue;
			result.transactions = x_results.transactions;
			result.ecomm_conversions = x_results.ecomm_conversions;
			// goals -----------------------------------------------
			// empty array for no values, else struct
			if ( x_results.goals == null ||
				 x_results.goals.GetType().Name.ToLower() == "array" ) return result;
			//
			Array goalsArray = x_results.goals as Array;
			IEnumerator ge = goalsArray.GetEnumerator();
			while ( ge.MoveNext() )
			{
				int it;
				IDictionary goal = ge.Current as IDictionary;
				string name = goal["name"].ToString();
				int.TryParse( goal["conversions"].ToString(), out it );
				result.goals.Add( name, it );
			}
			//
			return result;
		}

		#endregion
	}
}
